#ifndef ForwardRateSequence_hpp
#define ForwardRateSequence_hpp

#include "timeSequence.hpp"
#include <vector>
namespace TermStructure
{
	//! A Sequence of Forward Rate Based on a Given Time Sequence.
	/*! Forward Rate Sequence is the defined as the F_i for a time T_i,
	 and a time span Tau_i. The rate is from T_{i-1} to T_{i}, therefore
	 the first rate in the sequence is meaningless because it is F_0 
    */
	template <typename T, typename TSize = long>
	class ForwardRateSequence
	{
        //! The underlying time sequence
		TimeSequence<T,TSize> *_times;
        //! The forward rates stored
		std::vector<T> _forwardRates;
        //! Discount factors
		mutable std::vector<T> _discountFactors;
	public:
        //! Current Time
		T CurrentTime;
        //! Set the forward rate to a time sequence
        /*! Set the forward rate to a time sequence, the forward rates already
        in the sequence will be flushed */
		void SetTimeSequence(TimeSequence<T,TSize> &times)
		{
			this->_times = &times;
			this->_forwardRates.resize(this->_times->GetSize());
		}
		//! Get the underlying time sequence		
		const TimeSequence<T,TSize> &GetTimeSequence() const
		{
			return *this->_times;
		}
        //! Get the forward rate from Time_{i-1} to Time_i
		const T &ForwardRateAt(TSize i) const
		{
			return _forwardRates[i];
		}
        //! Get the forward rate from Time_{i-1} to Time_i
		T &ForwardRateAt(TSize i)
		{
			return _forwardRates[i];
		}
        //! Get the forward rate from Time_{i-1} to Time_i
		T &operator[](TSize i)
		{
			return _forwardRates[i];
		}
        //! Get the forward rate from Time_{i-1} to Time_i
		const T&operator[](TSize i) const
		{
			return _forwardRates[i];
		}
        //! Establish Discount Factors
		const ForwardRateSequence &EstablishDiscountFactors() const
		{
			this->_discountFactors.resize(this->_times->GetSize());
			this->_discountFactors[0] = 1;
			for(TSize i = 1; i < this->_times->GetSize(); i++)
			{
				this->_discountFactors[i] = this->_discountFactors[i-1] /(1+ this->_times->TimeDifference(i)*this->_forwardRates[i]);
			}
			return *this;
		}
        bool IsDiscountFactorEstablished() const
        {
            return (this->_discountFactors.size() == this->_times->GetSize());
        }
        //! Get the discount factors at Time_i
		T DiscountFactorAt(TSize fromT, TSize base = 0) const
		{
			return this->_discountFactors[fromT]/this->_discountFactors[base];
		}
        //! 
		T SwapRate(TSize fromT, TSize toT) const
		{
			T sum = 0;
			for(TSize i = fromT + 1; i <= toT; i++)
			{
				sum += this->_discountFactors[i] * this->_times->TimeDifference(i);
			}
			return (this->_discountFactors[fromT] - this->_discountFactors[toT])/sum;
		}
		TSize GetSize() const
		{
			return this->GetTimeSequence().GetSize();
		}
	};
}
#endif